package org.mcflier.appuntamento.i18n;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;

import org.mcflier.appuntamento.core.exception.PropertiesException;
import org.mcflier.appuntamento.core.properties.PropertiesManager;
import org.mcflier.appuntamento.i18n.exception.I18NCountryNotFoundException;
import org.mcflier.appuntamento.i18n.exception.I18NLanguageNotFoundException;

public class I18N {

	private static I18N instance;
	private static final String I18N_LANGUAGE_TAG = "application_language";
	private static final String I18N_COUNTRY_TAG = "application_country";
	private static final String I18N_DEFAULT_LANGUAGE = "en";
	private static final String I18N_DEFAULT_COUNTRY = "US";

	public static final String I18N_COUNTRY_BUNDLE = "org.mcflier.appuntamento.i18n.bundles.i18n.CountryResourceBundle";
	public static final String I18N_LANGUAGE_BUNDLE = "org.mcflier.appuntamento.i18n.bundles.i18n.LanguageResourceBundle";

	static{
		instance = null;
	}

	private Properties properties;

	private Language appLanguage;
	private Country appCountry;

	private Map<String, ResourceBundle> bundles;

	public static I18N getInstance() throws PropertiesException{
		if(instance == null)
			instance = new I18N();

		return instance;
	}

	private I18N() throws PropertiesException{
		this.bundles = new HashMap<String, ResourceBundle>();

		PropertiesManager propertiesManager = PropertiesManager.getInstance();
		this.properties = propertiesManager.getProperties();
		String lang = this.properties.getProperty(I18N_LANGUAGE_TAG, I18N_DEFAULT_LANGUAGE);
		String ctry = this.properties.getProperty(I18N_COUNTRY_TAG, I18N_DEFAULT_COUNTRY);

		/*Temporary language and country. Improve this!!*/
		this.appLanguage = new Language(lang, "XXXX");
		this.appCountry = new Country(ctry, "XXXX");
		/*End of crap*/

		this.appLanguage = new Language(lang, this.getResourceBundle(I18N_LANGUAGE_BUNDLE).getString(lang));
		this.appCountry = new Country(ctry, this.getResourceBundle(I18N_COUNTRY_BUNDLE).getString(ctry));
	}

	private ResourceBundle getResourceBundle(String resourceBundle){
		if(resourceBundle == null)
			throw new NullPointerException(this.getClass().getCanonicalName()+": Resource bundle must not be null");
		if(this.bundles.containsKey(resourceBundle))
			return this.bundles.get(resourceBundle);
		else{
			ResourceBundle resource = ResourceBundle.getBundle(resourceBundle, new Locale(this.appLanguage.getCode(), this.appCountry.getCode()));			
			this.bundles.put(resourceBundle, resource);
			return resource;
		}
	}

	public Language getAppLanguage(){
		return this.appLanguage;
	}

	public void setAppLanguage(String code) throws I18NLanguageNotFoundException, PropertiesException{
		try{
			this.appLanguage = new Language(code.trim().toLowerCase(), this.getResourceBundle(I18N_LANGUAGE_BUNDLE).getString(code.trim().toLowerCase()));
			this.properties.setProperty(I18N_LANGUAGE_TAG, code.trim().toLowerCase());
		}
		catch(NullPointerException except){
			throw new I18NLanguageNotFoundException("Language \""+code+"\" not found", except);
		}
	}

	public Country getAppCountry(){
		return this.appCountry;
	}

	public void setAppCountry(String code) throws I18NCountryNotFoundException, PropertiesException{
		this.appCountry = this.createCountry(code);
		this.properties.setProperty(I18N_COUNTRY_TAG, code.trim().toUpperCase());
	}

	public Country createCountry(String code) throws I18NCountryNotFoundException{
		try{
			Country country = new Country(code.trim().toUpperCase(), this.getResourceBundle(I18N_COUNTRY_BUNDLE).getString(code.trim().toUpperCase()));
			return country;
		}
		catch(NullPointerException except){
			throw new I18NCountryNotFoundException("Country \""+code+"\" was null", except);
		}
		catch(MissingResourceException except){
			throw new I18NCountryNotFoundException("Country \""+code+"\" not found", except);
		}
	}

	public Language createLanguage(String code) throws I18NLanguageNotFoundException{
		try {
			Language language = new Language(code.trim().toLowerCase(), this.getResourceBundle(I18N_LANGUAGE_BUNDLE).getString(code.trim().toLowerCase()));
			return language;
		} catch (NullPointerException e) {
			throw new I18NLanguageNotFoundException("Language \""+code+"\" was null", e);
		} catch (MissingResourceException e) {
			throw new I18NLanguageNotFoundException("Language \""+code+"\" not found", e);
		}
	}
}